#include <WINSOCK2.H>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define PORT 7000

void pe(char *info){
	printf("%s %d\n",info, WSAGetLastError());
}


int main()
{
	SOCKET s, c;
	int total = 0;
	SOCKET clients[FD_SETSIZE];
	SOCKADDR_IN saddr, caddr;
	WSADATA wsdata;
	int ret, len;
	fd_set fdread;
	timeval tv;
	unsigned long block;
	
	ret = WSAStartup(MAKEWORD(1, 1), &wsdata);
	
	
	s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(PORT);
	saddr.sin_addr.s_addr = htonl(INADDR_ANY);
	ret = bind(s, (LPSOCKADDR)&saddr, sizeof(saddr));
	ret = listen(s, 5);
	
	len = sizeof(caddr);
	
	tv.tv_sec = 2;
	tv.tv_usec = 0;
	
	ret = ioctlsocket(s, FIONBIO, &block);
	
	while(true){
		FD_ZERO(&fdread);
		for(int i = 0; i < total; i++){
			FD_SET(clients[i], &fdread);
		}
		FD_SET(s, &fdread);
		
		
		ret = select(0, &fdread, NULL, NULL, &tv);
		if(ret == SOCKET_ERROR){
			printf("error:%d\n", WSAGetLastError());
			return -1;
		}
		
		if (FD_ISSET(s, &fdread)){
			c = accept(s, (LPSOCKADDR)&caddr, &len);
			if (c != INVALID_SOCKET){
				clients[total++] = c;
				printf("new client in\n");
				printf("ip:%s\n", inet_ntoa(caddr.sin_addr));
				printf("port:%d\n", ntohs(caddr.sin_port));

			}else {
				printf("error:\n", WSAGetLastError());
				continue;
			}
		}
		for (int j = 0; j < total; j++){
			if (FD_ISSET(clients[j], &fdread)){
				char buffer[100] = {0};
				if (recv(clients[j], buffer, 100, 0) != SOCKET_ERROR){
					puts(buffer);
				}else{
					printf("client[%d], error:%d\n", j, WSAGetLastError());
					clients[total--] = NULL;//BUG.should be linked list
					closesocket(clients[j]);
					break;
				}
			}
		}
	}
	
	closesocket(s);
	WSACleanup();
	return 0;
}